#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
THN MVC MODULE FOR THN WEB SERVER

Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

This library is dual-licensed.
  + For use in commercial software, please obtain a commercial license from THN Solutions LLC.    

  + For use in free software, this library is licensed under GPL version 3. A summary of 
	GPLv3 is listed below. You should also find a copy of GPLv3 as file License_GPLv3.txt 
	included with the source-code files.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 3 as published by
    the Free Software Foundation  of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#endregion

#region Record of Change
//             							CHANGE HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | DEVELOPER  | DESCRIPTION                                              |
// -------------------------------------------------------------------------------------
// | 03-May-10 | HaiNM      | First creation.                                          |
// -------------------------------------------------------------------------------------
//
#endregion

#region Record of Audit
//             							REVIEW HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | REVIEWER   | NOTES                                                    |
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
//
#endregion

#region Using directives
using System;
using System.ComponentModel;
using System.Windows.Forms;

using Thn;
using Thn.Logging;
#endregion

namespace Demo
{
    /// <summary>
    /// Example of creating a log viewer by hand. This example shall write log entries to a ListView.
    /// </summary>
    [ToolboxItem(true)]
#if DEBUG
    public
#else
    public
#endif
 class LogViewer : Component, ILogListener
    {
        #region Fields
        ListViewGroup mGroup = null;
        #endregion

        #region Properties

        #region Target
        private ListView mTarget;
        /// <summary>
        /// Gets/Sets target.
        /// </summary>        
        public ListView Target
        {
            get { return mTarget; }
            set
            {
                mTarget = value;
                if (mTarget != null)
                {
                    SetupTarget(mTarget);
                }
                #region Defensive tracing
                else
                {
                    //no instance to setup
                }
                #endregion
            }
        }
        #endregion

        #endregion

        #region Setup Target

        void SetupTarget(ListView target)
        {
            if (target.Columns.Count != 5)
            {
                target.Columns.Clear();

                ColumnHeader hTime = new ColumnHeader("Time");
                hTime.Text = "Time";
                hTime.Width = 75;
                hTime.TextAlign = HorizontalAlignment.Center;
                target.Columns.Add(hTime);

                ColumnHeader hType = new ColumnHeader("Type");
                hType.Text = "Type";
                hType.Width = 75;
                hType.TextAlign = HorizontalAlignment.Center;
                target.Columns.Add(hType);

                ColumnHeader hMessage = new ColumnHeader("Message");
                hMessage.Text = "Message";
                hMessage.Width = 550;
                target.Columns.Add(hMessage);
            }
            #region Defensive tracing
            else
            {
                //already setup
            }
            #endregion

            target.View = View.Details;
        }

        #endregion

        #region Write Entry
        void WriteEntry(ILogEntry entry, int scopeId, int scopeLevel)
        {
            DateTime t = entry.Time;
            string time = string.Format("{0:00}:{1:00}:{2:00}.{3:000}", t.Hour, t.Minute, t.Second, t.Millisecond);
            string type = entry.GetType().Name.Replace("Log", "");
            string message = "";
            //make indentations
            //for (int i = 0; i < mIndentation; i++)
            for (int i = 0; i < scopeLevel; i++)
            {
                message += "     ";
            }

            //actual message
            message += entry.Message;
            //message += string.Format("{0} - Message: {1} - Description: {2} - Time: {3}", entry.GetType().Name, entry.Message, entry.Description, entry.Time);

            //Add to target listbox
            ListViewItem item = new ListViewItem(new string[] { time, type, message });
            mTarget.Items.Add(item);

            //scroll down to the last item
            mTarget.EnsureVisible(mTarget.Items.Count - 1);
            //mTarget.SelectedIndex = mTarget.Items.Count - 1;
        }
        #endregion

        #region Process Write
        void ProcessWrite(object item, int scopeId, int scopeLevel)
        {
            mTarget.SuspendLayout();

            if (item is ILogEntryCollection)
            {
                ILogEntryCollection entries = (ILogEntryCollection)item;
                foreach (var entry in entries)
                {
                    WriteEntry(entry, scopeId, scopeLevel);
                }
            }
            else WriteEntry((ILogEntry)item, scopeId, scopeLevel);

            mTarget.ResumeLayout();
        }

        delegate void WriteHandler(object item, int scopeId, int scopeLevel);
        WriteHandler ProcessWriteCallback;
        #endregion

        #region ILogViewer Members

        #region Write
        /// <summary>
        /// Write a log entry.
        /// </summary>
        /// <param name="entry">The entry to write.</param>
        /// <param name="scopeId">Current scope's identifier.</param>
        /// <param name="scopeLevel">Current scope's level.</param>
        public void Write(ILogEntry entry, int scopeId, int scopeLevel)
        {
            if (mTarget != null)
            {
                if (mTarget.InvokeRequired)
                {
                    //thread-safe UI update
                    mTarget.Invoke(ProcessWriteCallback, entry, scopeId, scopeLevel);
                }
                else
                {
                    //same thread as UI, process directly
                    ProcessWrite(entry, scopeId, scopeLevel);
                }
            }
            #region Defensive tracing
            else
            {
                //target not assigned yet.
            }
            #endregion
        }
        #endregion

        #region Write - Collection
        /// <summary>
        /// Write collection of entries.
        /// </summary>
        /// <param name="entry">The entry to write.</param>
        /// <param name="scopeId">Current scope's identifier.</param>
        /// <param name="scopeLevel">Current scope's level.</param>
        public void Write(ILogEntryCollection entries, int scopeId, int scopeLevel)
        {
            if (mTarget != null)
            {
                if (mTarget.InvokeRequired)
                {
                    //thread-safe UI update
                    mTarget.Invoke(ProcessWriteCallback, entries, scopeId, scopeLevel);
                }
                else
                {
                    //same thread as UI, process directly
                    ProcessWrite(entries, scopeId, scopeLevel);
                }
            }
            #region Defensive tracing
            else
            {
                //target not assigned yet.
            }
            #endregion
        }
        #endregion

        #region Begin Scope
        /// <summary>
        /// This method is raised when a new scope is found.
        /// </summary>
        /// <param name="scopeLevel">Level of the provided scope.</param>
        public void BeginScope(ILogScope scope, int scopeLevel)
        {
            //mIndentation = scopeLevel;
            Write(scope, scope.ScopeId, scopeLevel);
        }
        #endregion

        #region End Scope
        /// <summary>
        /// This method is raised when a scope is ended.
        /// </summary>
        /// <param name="scopeId">Identifier of the scope to be ended.</param>
        /// <param name="scopeLevel">Level of the provided scope.</param>
        public void EndScope(int scopeId, int scopeLevel)
        {
            //mIndentation = scopeLevel;
        }
        #endregion

        #region Shutdown
        /// <summary>
        /// This method is raised by the logger before it shutdowns.
        /// </summary>
        public void Shutdown()
        {
            //this listener has nothing to clean up on shutting down.
        }
        #endregion

        #endregion

        #region Constructors
        /// <summary>
        /// Default constructor.
        /// </summary>
        public LogViewer()
        {
            ProcessWriteCallback = new WriteHandler(ProcessWrite);
            Log.Logger.RegisterListener(this);
        }
        #endregion
    }
}
